import asyncio
import json
import logging
from json import JSONDecodeError
from src64.models.user_info import json2UserInfo
import websockets
from websockets.exceptions import ConnectionClosedError

"""
    信息的入口类,所有的事件都在这里进行处理分发
"""


class MainEntry:
    def __init__(self, report, serial_port, conf):
        self.report = report
        self.serial_port = serial_port
        self.user_info = None
        self.conf = conf
        self.logger = logging.getLogger('main')

    async def register(self, websocket, *args):
        """
        监听前端消息
        :param websocket:
        :param args:
        :return:
        """
        if self.report:
            self.report.CONNECTION_SET.add(websocket)
        if self.serial_port:
            self.serial_port.CONNECTIONS.add(websocket)
        try:
            async for message in websocket:
                try:
                    event = json.loads(message)

                    self.logger.info('json:{}'.format(event))
                    type_exam = event['type']
                    if type_exam == 'ping':
                        await websocket.send(json.dumps({"type": "pong"}))

                    elif type_exam == 'info':
                        # 如果前端发送患者信息,则判断当前是否能够进行数据的插入
                        if self.report and self.report.SET_INFO == '1' and 'info' in event:
                            if self.conf.has_section(section='access') or self.conf.has_section(section='sqlite'):
                                await self.report.insert_info_to_db(event['info'])
                            elif self.conf.has_option('base', 'file_path'):
                                self.logger.info('insert_info_to_file')
                                await self.report.insert_info_to_file(event['info'])
                    elif type_exam == 4:
                        # 根据体检号查找体检报告图片
                        examNo = event['examNo']
                        if self.report:
                            pic = await self.report.find_pic_by_dir(examNo)
                            info = await self.report.select_info_by_no(examNo)
                            data = None
                            if info:
                                data = {"result": info[7], "value": info[6]}
                            await websocket.send(json.dumps({"type": type_exam, "pic": pic, "data": data}))
                    elif type_exam == 'login':
                        # 医生登录,记录医生信息
                        self.user_info = json.loads(message, object_hook=json2UserInfo)
                        self.logger.info("socket:{}".format(self.user_info))
                        self.report.set_user_info(self.user_info)
                    elif type_exam == 'logout':
                        # 医生退出登录,清除医生信息
                        self.user_info = None
                        self.report.user_info = None
                    elif 'examNo' in event:
                        if self.serial_port:
                            self.serial_port.setExamNo(type_exam=type_exam, examNo=event['examNo'])
                    else:
                        await websocket.send('{"type":-1,"data":"undefined"}')
                except JSONDecodeError as e:
                    self.logger.error('解析出错:{}'.format(e))
                except KeyError as e:
                    self.logger.error('没有对应的key值:{}'.format(e))
                except ConnectionClosedError as e:
                    self.logger.error('error:{}'.format(e))
                except Exception as e:
                    self.logger.error('error:{}'.format(e))
        finally:
            if self.report:
                self.report.CONNECTION_SET.remove(websocket)
            if self.serial_port:
                self.serial_port.CONNECTIONS.remove(websocket)
            await websocket.send('close')
            self.logger.info('websocket is close')

    def start(self):
        start_server = websockets.serve(self.register, 'localhost', 8765)
        asyncio.get_event_loop().run_until_complete(start_server)
        asyncio.get_event_loop().run_forever()
